package hyl.core.io;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import hyl.core.AIni;
import hyl.core.MyFun;

/*
 * * java <br>
getPathOfClass()=/D:/work/java/hyl.core/target/classes/hyl/core/conf/
getPathOfClasses()=/D:/work/java/hyl.prod-bracelet/target/classes/
getPathOfPro()=D:\work\java\hyl.prod-bracelet\
getSystemResource()=file:/D:/work/java/hyl.prod-bracelet/target/classes/
getPathOfJar()=D:\work\java\hyl.core\target
AppClassLoader=C:\Program Files\Java\jdk1.8.0_202\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\zipfs.jar;D:\work\java\hyl.prod-bracelet\target\classes;D:\work\java\hyl.core\target\classes;D:\maven-repository\org\slf4j\slf4j-log4j12\1.7.25\slf4j-log4j12-1.7.25.jar;D:\maven-repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;D:\maven-repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;D:\maven-repository\com\alibaba\fastjson\1.2.49\fastjson-1.2.49.jar;D:\maven-repository\com\esotericsoftware\kryo\4.0.2\kryo-4.0.2.jar;D:\maven-repository\com\esotericsoftware\reflectasm\1.11.3\reflectasm-1.11.3.jar;D:\maven-repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;D:\maven-repository\com\esotericsoftware\minlog\1.3.0\minlog-1.3.0.jar;D:\maven-repository\org\objenesis\objenesis\2.5.1\objenesis-2.5.1.jar;D:\maven-repository\org\mariadb\jdbc\mariadb-java-client\2.2.6\mariadb-java-client-2.2.6.jar;D:\maven-repository\org\apache\commons\commons-lang3\3.8\commons-lang3-3.8.jar;D:\maven-repository\javax\mail\mail\1.4.7\mail-1.4.7.jar;D:\maven-repository\javax\activation\activation\1.1\activation-1.1.jar;D:\eclipse\plugins\org.junit.jupiter.api_5.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.jupiter.engine_5.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.jupiter.migrationsupport_5.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.jupiter.params_5.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.platform.commons_1.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.platform.engine_1.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.platform.launcher_1.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.platform.runner_1.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.platform.suite.api_1.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit.vintage.engine_5.1.0.v20180327-1502.jar;D:\eclipse\plugins\org.opentest4j_1.0.0.v20180327-1502.jar;D:\eclipse\plugins\org.apiguardian_1.0.0.v20180327-1502.jar;D:\eclipse\plugins\org.junit_4.12.0.v201504281640\junit.jar;D:\eclipse\plugins\org.hamcrest.core_1.3.0.v20180420-1519.jar;D:\work\java\hyl.base.mq\target\classes;D:\maven-repository\org\apache\rocketmq\rocketmq-client\4.3.0\rocketmq-client-4.3.0.jar;D:\maven-repository\org\apache\rocketmq\rocketmq-common\4.3.0\rocketmq-common-4.3.0.jar;D:\maven-repository\org\apache\rocketmq\rocketmq-remoting\4.3.0\rocketmq-remoting-4.3.0.jar;D:\maven-repository\io\netty\netty-all\4.0.42.Final\netty-all-4.0.42.Final.jar;D:\maven-repository\org\apache\rocketmq\rocketmq-logging\4.3.0\rocketmq-logging-4.3.0.jar;D:\maven-repository\io\netty\netty-tcnative-boringssl-static\1.1.33.Fork26\netty-tcnative-boringssl-static-1.1.33.Fork26.jar;D:\maven-repository\org\apache\kafka\kafka-clients\2.4.1\kafka-clients-2.4.1.jar;D:\maven-repository\com\github\luben\zstd-jni\1.4.3-1\zstd-jni-1.4.3-1.jar;D:\maven-repository\org\lz4\lz4-java\1.6.0\lz4-java-1.6.0.jar;D:\maven-repository\org\xerial\snappy\snappy-java\1.1.7.3\snappy-java-1.1.7.3.jar;D:\maven-repository\org\apache\activemq\activemq-client\5.15.10\activemq-client-5.15.10.jar;D:\maven-repository\org\apache\geronimo\specs\geronimo-jms_1.1_spec\1.1.1\geronimo-jms_1.1_spec-1.1.1.jar;D:\maven-repository\org\fusesource\hawtbuf\hawtbuf\1.11\hawtbuf-1.11.jar;D:\maven-repository\org\apache\geronimo\specs\geronimo-j2ee-management_1.1_spec\1.0.1\geronimo-j2ee-management_1.1_spec-1.0.1.jar;D:\maven-repository\com\rabbitmq\amqp-client\5.7.3\amqp-client-5.7.3.jar;D:\maven-repository\org\eclipse\paho\org.eclipse.paho.client.mqttv3\1.2.2\org.eclipse.paho.client.mqttv3-1.2.2.jar;D:\maven-repository\org\fusesource\mqtt-client\mqtt-client\1.16\mqtt-client-1.16.jar;D:\maven-repository\org\fusesource\hawtdispatch\hawtdispatch-transport\1.22\hawtdispatch-transport-1.22.jar;D:\maven-repository\org\fusesource\hawtdispatch\hawtdispatch\1.22\hawtdispatch-1.22.jar;D:\work\java\hyl.ext.web\target\classes;D:\maven-repository\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;D:\work\java\hyl.base.cache\target\classes;D:\maven-repository\org\ehcache\ehcache\3.6.2\ehcache-3.6.2.jar;D:\maven-repository\redis\clients\jedis\3.2.0\jedis-3.2.0.jar;D:\maven-repository\org\apache\commons\commons-pool2\2.6.2\commons-pool2-2.6.2.jar;D:\work\java\hyl.base.flow\target\classes;D:\eclipse\configuration\org.eclipse.osgi\418\0\.cp\lib\javaagent-shaded.jar
ExtClassLoader=C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
getLastPathOfClassLoader()=/D:/work/java/hyl.prod-bracelet/target/
 * 
 * <br>
 * junit <br>
 * getPathOfClassLoader()=/F:/ecwork/hyl.test/target/test-classes/ <br>
 * getPathOfClass()=/F:/ecwork/hyl.core/target/classes/hyl/core/conf/ <br>
 * getPathOfPro()=F:\ecwork\hyl.test <br>
 * getURIOfClassLoader()=file:/F:/ecwork/hyl.test/target/test-classes/ <br>
 * 作废 getSystemResource()=file:/F:/ecwork/hyl.test/target/test-classes/ <br>
 * getPathOfJar()=F:\ecwork\hyl.core\target <br>
 * getPathArrayOfImportClasses()=F:\ecwork\hyl.test\target\test-classes;F:\ecwork\hyl.test\target\classes;....
 * <br>
 * getPathOfProject()=/F:/ecwork/hyl.test/ <br>
 * getSrcPathOfProject()=/F:/ecwork/hyl.test/target/ <br>
 * <br>
 * <br>
 * web <br>
 * getPathOfClass()=file:/D:/work/java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/hyl.prod-bracelet/WEB-INF/lib/hyl.core.jar!/hyl/core/conf/
getPathOfClasses()=/D:/work/java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/hyl.prod-bracelet/WEB-INF/classes/
getPathOfPro()=D:\eclipse\
getSystemResource()=null
getPathOfJar()=D:\work\java\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\hyl.prod-bracelet\WEB-INF\lib
AppClassLoader=C:\Program Files\Java\jdk1.8.0_202\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfr.jar;D:\tools\apache-tomcat-8.5.33\bin\bootstrap.jar;D:\tools\apache-tomcat-8.5.33\bin\tomcat-juli.jar;C:\Program Files\Java\jdk1.8.0_202\lib\tools.jar
ExtClassLoader=C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
getLastPathOfClassLoader()=/D:/work/java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/hyl.prod-bracelet/WEB-INF/
*/
/**
 * 
 * Class.getResource(String path)<br>
 * path不以'/'开头时，默认是从此类所在的包下取资源；<br>
 * * path以'/'开头时，则是从项目的ClassPath根下获取资源。在这里'/'表示ClassPath的根目录。<br>
 * 
 * Class.getClassLoader().getResource(String path)<br>
 *      path不能以'/'开头，path是指类加载器的加载范围，从编译的根目录开始<br>
 * 
 * <br>
 * ClassLoader=指向 classes 目录<br>
 * 编译路径=ClassLoader + 类包路径 +类名 <br>
 * 
 * 
 * Class.getClassLoader（）.getResource(String path) path不能以’/'开头时； <br>
 * path是从ClassPath根下获取； Class.getResource(String path) <br>
 * path不以’/'开头时，默认是从此类所在的包下取资源； path 以’/'开头时，则是从ClassPath根下获取； <br>
 * 
 * 
 * @ClassName: MyPath
 * @Description: TODO
 * @author zoudy
 * @date 2018年2月26日 下午6:06:32
 * @version V1.0
 */
public class MyPath {
	private static final Logger log = LoggerFactory.getLogger(MyPath.class);
	private static final String ERRNOFILE = "文件不存在";

	public static void test(Class<?> clazz) {
		// show程序基础属性();
		System.out.println("getPathOfClass()=" + getPathOfClass(MyPath.class));
		System.out.println("getPathOfClasses()=" + getPathOfClasses(MyPath.class));

		System.out.println("getPathOfPro()=" + getPathOfPro());
		System.out.println("getSystemResource()=" + getSystemResource("config.json"));
		System.out.println("getPathOfJar()=" + getPathOfJar(clazz));
		System.out.println("AppClassLoader=" + getPathOfAppClassLoader());
		System.out.println("ExtClassLoader=" + getPathOfExtClassLoader());
		System.out.println("getLastPathOfClassLoader()=" + getLastPathOfClassLoader(clazz.getClassLoader()));
		Properties properties = System.getProperties();
		System.out.println("java.class.path::" + properties.getProperty("java.class.path"));
		System.out.println("getPathOfAppClassLoader()=" + MyPath.getPathOfAppClassLoader());
		System.out.println("java.endorsed.dirs::" + properties.getProperty("java.endorsed.dirs"));
		System.out.println("user.dir::" + properties.getProperty("user.dir"));
		System.out.println("java.io.tmpdir::" + properties.getProperty("java.io.tmpdir"));
		System.out.println("java.library.path::" + properties.getProperty("java.library.path"));
		System.out.println("user.home::" + properties.getProperty("user.home"));
		System.out.println("java.ext.dirs::" + properties.getProperty("java.ext.dirs"));
		System.out.println("sun.boot.class.path::" + properties.getProperty("sun.boot.class.path"));

	}

	public static void show程序基础属性() {
		Properties properties = System.getProperties();
		Set<Map.Entry<Object, Object>> set = properties.entrySet();
		for (Map.Entry<Object, Object> objectObjectEntry : set) {
			System.out.println(objectObjectEntry.getKey() + ":" + objectObjectEntry.getValue());
		}
	}

	public static void show程序环境变量() {
		Map<String, String> map = System.getenv();
		Set<Map.Entry<String, String>> entries = map.entrySet();
		for (Map.Entry<String, String> entry : entries) {
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}
	}

	public static String sfind(String 查找目录或文件) {
		return MyFile.find(查找目录或文件).getPath().replace('\\', '/');
	}

	public static String sfind(File 从当前目录, String 查找目录或文件) {
		return MyFile.find(从当前目录, 查找目录或文件).getPath().replace('\\', '/');
	}

	/**
	 * 返回类的路径
	 * 
	 * @param clazz
	 * @return
	 */
	public static String getPathOfClass(Class<?> clazz) {
		if (clazz == null)
			return null;
		try {
			return clazz.getResource("").getPath();
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 返回类的根路径
	 * 
	 * @param clazz
	 * @return
	 */
	public static String getPathOfClasses(Class<?> clazz) {
		if (clazz == null)
			return null;
		try {
			return clazz.getResource("/").getPath();
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 返回 filepath 的绝对路径 从class, test-class, web/class 都会找一遍 注意 filepath 必须用/开头
	 * 先找到就返回
	 */
	public static String getPathOfClass(Class<?> clazz, String filepath) {
		URL u = clazz.getResource(filepath);
		if (u == null)
			return null;
		return u.getPath();
	}

	/**
	 * 从class, test-class, web/class 都会找一遍 filepath 相对文件 <br>
	 * 注意 filepath不能用 /开头 <br>
	 * ClassLoader 可以载入多个jar 所以这个函数只是适合 单目录 ,多目录时 异常
	 * 
	 * @param clazz
	 * @return 返回 类编译后的存放根目录
	 * 
	 * 
	 */
	public static String getPathOfClassLoader(ClassLoader clazzloader) {
		if (clazzloader == null)
			return null;
		return clazzloader.getResource("").getPath();
	}

	public static String getPathOfClassLoader(ClassLoader clazzloader, String filepath) {
		if (clazzloader == null)
			return null;
		URL u = clazzloader.getResource(filepath);
		if (u == null)
			return null;
		return u.getPath();
	}

	/**
	 * 返回类编译后的路径,不含类文件名 指向 classes 目录的上一层 target 目录 或者web-INF目录
	 * 
	 * @param clazz
	 * @return
	 */
	public static String getLastPathOfClassLoader(ClassLoader clazz) {
		String s = getPathOfClassLoader(clazz, "");
		if (MyFun.isEmpty(s))
			return null;
		String a = null;
		if (s.indexOf("classes/") > 0)
			a = s.substring(0, MyString.findChar(s, '/', -2) + 1);
		else
			a = s;
		// System.out.println("mypath.161行:"+a);
		return a;
	}

	/**
	 * new File("").getCanonicalPath() 等价于 System.getProperty("user.dir")
	 * 
	 * @return D:\git\hyl.test
	 * @throws IOException
	 * @Description:返回程序根目录
	 */
	public static String getPathOfPro() {
		// new File("").getCanonicalPath() 等价于 System.getProperty("user.dir")

		return System.getProperty("user.dir") + File.separatorChar;
	}

	/**
	 * 过期了 不要用 但是有参考意义
	 * <p>
	 * classLoader的getSystemResource方法类似于classLoader的方法，相当于使用系统的classLoader然后调用getResource
	 * </p>
	 * <p>
	 * Description:
	 * ClassLoader.getSystemResource等价于ClassLoader.getSystemClassLoader().getResource("")
	 * 用 getPathOfClasses(MyPath.class,file) 代替
	 * </p>
	 * 
	 * @return file:/D:/git/hyl.test/target/classes/
	 */

	public static String getSystemResource(String file) {
		// return obj.getClass().getResource(".").getPath();
		URL s = ClassLoader.getSystemResource(file);
		if (s == null)
			return null;
		return s.getPath();
	}

	/**
	 * 返回class 的jar文件 所在位置
	 * 
	 * @param clazz
	 * @return
	 */
	public static String getPathOfJar(Class<?> clazz) {
		if (clazz == null)
			return null;
		String path = clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
		// System.out.println(path);
		try {
			path = java.net.URLDecoder.decode(path,AIni.Charset);
			java.io.File jarFile = new java.io.File(path);
			return java.net.URLDecoder.decode(jarFile.getParentFile().getAbsolutePath(),AIni.Charset);
		} catch (java.io.UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String getPathOfAppClassLoader() {
		return System.getProperty("java.class.path");
	}

	public static String getPathOfExtClassLoader() {
		return System.getProperty("java.ext.dirs");
	}

	/**
	 * 返回 所有java.class.path
	 * 
	 * @return
	 */
	public static String[] getPathsOfPackage() {
		String[] pp = getPathOfAppClassLoader().split(";");
		return pp;
	}

	/**
	 * 获取类路径去掉.class 后的字符串
	 * 
	 * @param classPath
	 * @return
	 */
	public static String getClassNameOfString(String classPath) {
		if (MyFun.isEmpty(classPath))
			return "";

		int b = classPath.lastIndexOf(".class");
		int a = classPath.lastIndexOf(".", b - 1);
		// System.out.println(a);
		// System.out.println(b);
		return classPath.substring(a + 1, b);
	}

	/**
	 * 截取类路径 排除 .class 后缀
	 * 
	 * @param classPath
	 * @return
	 */
	public static String getPackPathOfString(String classPath) {
		if (MyFun.isEmpty(classPath))
			return "";
		return classPath.substring(0, classPath.lastIndexOf('.'));
	}

	/**
	 * 把 xx.xx.xx.xx 的路径转为 /xx/xx/的路径 并且去掉 .class 后缀
	 * 
	 * @param url
	 * @return
	 */
	public static String uri2PackPath(String url) {
		// 去掉后缀.class
		if (url.indexOf(".class") >= 0)
			url = url.substring(0, url.length() - 6);
		return url.replace("/", ".").replace("\\", ".");
	}

	/**
	 * 返回编译路径下的文件的流对象 <br>
	 * 替换为 getInputStreamFromClassLoadFile
	 * 
	 * @param filename
	 * @return
	 */
	@Deprecated
	public static InputStream getInputStreamFromClassFile(String filename) {
		return getInputStreamOfFile(MyPath.class, filename);
	}

	/**
	 * 返回某个对象实例的编译路径下的文件的流对象
	 * 
	 * @param object
	 * @param filename
	 * @return
	 */

	public static InputStream getInputStreamOfFile(Object object, String filename) {
		return getInputStreamOfFile(object.getClass(), filename);
	}

	/**
	 * filename 路径前面加/ 才从根路径开始找
	 * <p>
	 * Title: getInputStream
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param filename @return @return :InputStream @throws
	 */
	public static InputStream getInputStreamOfFile(Class<?> clazz, String filename) {
		try {
			if (clazz == null)
				clazz = null;
			return clazz.getResourceAsStream(filename);
		} catch (Exception e) {
			log.error(filename + ERRNOFILE);
			return null;
		}
	}

	/**
	 *
	 * @param clazz    默认从编译 的classes目录 开始查找文件
	 * @param filename 文件名前面不要加 /
	 * @return
	 */

	public static InputStream getInputStreamFromClassLoadFile(ClassLoader clazzloader, String filename) {
		try {
			// MyPath.class.getResourceAsStream(name)
			return clazzloader.getResourceAsStream(filename);
		} catch (Exception e) {
			log.error(filename + ERRNOFILE);
			return null;
		}
	}

	/**
	 * getSystemResourceAsStream 传入路径前面不需要加/ 默认从根路径开始找 <br>
	 * 区别于getResourceAsStream 传入路径前面加/ 才从根路径开始找 <br>
	 * 
	 * 
	 * 
	 * @param filename @return @return :InputStream @throws
	 */

	public static InputStream getInputStreamFromClassLoadFile(String filename) {
		return ClassLoader.getSystemClassLoader().getResourceAsStream(filename);
		// return ClassLoader.getSystemResourceAsStream(filename);
	}

	/**
	 * 返回文件名在字符串中的开始位置<br>
	 * 
	 */

	static int getFileNameBeginIndex(String url) {
		int i = url.lastIndexOf('\\');
		if (i < 0) {
			i = url.lastIndexOf('/');
		}
		if ((i + 1) == url.length()) {
			return -1;
		} else {
			return i + 1;
		}
	}

	/**
	 * 返回文件名在字符串中的结束位置<br>
	 * 
	 */

	static int getFileNameEndIndex(String url) {
		int i = url.lastIndexOf('?');
		if (i < 0) {
			return url.length();
		} else {
			return i;
		}
	}

	/**
	 * 返回文件名在字符串中的开始位置<br>
	 * 
	 */

	public static String getFileNameOfUrl(String url) {
		int begin = getFileNameBeginIndex(url);
		int end = getFileNameEndIndex(url);
		if (begin < 0 || end < begin || end == 0)
			return null;
		return url.substring(begin, end);
	}

}
